package com.jlh.viewer.thread;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * Created by jlh
 * On 2017/3/10 0010.
 */
public class SynchronziedTestList {
    public static  class ClassA{
        public synchronized void methodA() throws InterruptedException {
            for (int i=0;i<10;i++) {
                System.out.println(Thread.currentThread().getName()+"methodA" + LocalDateTime.now());
                TimeUnit.SECONDS.sleep(1);
            }
        }
        public synchronized void methodB () throws InterruptedException {
            for (int i=0;i<10;i++) {
                System.out.println(Thread.currentThread().getName()+"methodB" + LocalDateTime.now());
                TimeUnit.SECONDS.sleep(1);
            }
        }
        public static synchronized void methodC() throws InterruptedException {
            for (int i=0;i<10;i++) {
                System.out.println(Thread.currentThread().getName()+"methodC" + LocalDateTime.now());
                TimeUnit.SECONDS.sleep(1);
            }
        }

        public static void main(String[] args) throws InterruptedException {
            //Synchronized 锁在方法上的时候相当于是Synchronized (this) 所以同一个对象的两个方法不能同一时间访问
            // 会阻塞，对于不同对象则不阻塞， 监视对象的概念
            ClassA classA = new ClassA();
            //与其他轮流输出，因为锁对象是类，和this又不一样，即监视器不同
            new Thread(()->{
                try {
                    ClassA.methodC();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            new Thread(()->{
                try {
                    classA.methodA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            new Thread(()->{
                try {
                    classA.methodB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            //A或者B一方先输出完，才能让另一方输出
            ClassA classA1 = new ClassA();
            new Thread(()->{
                try {
                    classA1.methodA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            //与前两者无关独自输出 因为对象不同所以 synchronized this 也不同，即监视器不同
            TimeUnit.SECONDS.sleep(20);
        }
    }
}
